package javasec.contempt.visuals;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;

import javasec.contempt.data.SeedConnection;
import javasec.contempt.dialogs.StringDialog;
import javasec.seed.DataSeedInterface;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuDetectEvent;
import org.eclipse.swt.events.MenuDetectListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;


public class RemoteNetworkVisual extends EditorPart
{
	public static String ID = "javasec.contempt.visuals.RemoteNetworkVisual";
	//private Text entry;
	String tableName;
	private SeedConnection seedConnection=null;
	private Tree tree=null;
	private Display display=null;
	
	// store a lookup table for the items
	private HashMap<String,TreeItem> hostMap=new HashMap<String,TreeItem>();
	private HashMap<String,TreeItem> aMap=new HashMap<String,TreeItem>();
	private HashMap<String,TreeItem> bMap=new HashMap<String,TreeItem>();
	private HashMap<String,TreeItem> cMap=new HashMap<String,TreeItem>();
	
	public RemoteNetworkVisual()
	{
		// TODO Auto-generated constructor stub
	}

	public void doSave(IProgressMonitor monitor)
	{
		// TODO Auto-generated method stub

	}

	public void doSaveAs()
	{
		// TODO Auto-generated method stub

	}

	public void init(IEditorSite site, IEditorInput input)throws PartInitException
	{
		System.out.println("new database editor init()ed");
		// TODO Auto-generated method stub
		setSite(site);
		setInput(input);
		
		System.out.println("get the database name!");
		tableName=input.getName();
		seedConnection=((VisualInput)input).seedConnection;
		setPartName("remote networks");
	}

	public boolean isDirty()
	{
		// TODO Auto-generated method stub
		return false;
	}

	public boolean isSaveAsAllowed()
	{
		// TODO Auto-generated method stub
		return false;
	}
	
	public void createPartControl(Composite parent)
	{		
		// save display for async exec later
		display=Display.getCurrent();
		
		// create the table
		parent.setLayout(new GridLayout(1,false));
		tree = new Tree(parent,SWT.BORDER);
		tree.setLayoutData(new GridData(GridData.FILL_BOTH));
		//tree.setItemCount(256);
		
		try
		{
			for(Object[] host:seedConnection.dataSeed.selectAll("HOST"))
			{
				addHost(host);
			}
			
			for(Object[] service:seedConnection.dataSeed.selectAll("SERVICE"))
			{
				addService(service);
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
		// set the tree to expand when double clicked on (or enter)
		tree.addSelectionListener(new SelectionListener()
		{
			public void widgetDefaultSelected(SelectionEvent e)
			{
				if(e.item instanceof TreeItem)
				{
					TreeItem item=(TreeItem)e.item;
					item.setExpanded(!item.getExpanded());
				}
			}

			public void widgetSelected(SelectionEvent e)
			{
			}
		});
			
		// add the notifiers
		seedConnection.notifier.subscribe("data.newRow.HOST",this,"addHost");
		seedConnection.notifier.subscribe("data.newRow.SERVICE",this,"addService");
	}

	public void addHost(Object o) // called when a new target is added to the db
	{
		try
		{
			final Object[] row=(Object[])o;
			final String host=row[2].toString();
			final String a=row[3].toString();
			final String b=row[4].toString();
			final String c=row[5].toString();
			
			// make sure this isn't a 1918 address
			if(a.equals("10"))return;
			if(a.equals("192")&&b.equals("168"))return;
			if(a.equals("172")) //  damn /12 subnet
			{
				Integer bInt=new Integer(b);
				if(bInt>=16 && bInt<32)return;
			}
			
			display.syncExec(new Runnable()
			{
				public void run()
				{
					TreeItem hostItem=null;
					TreeItem aItem=null;
					TreeItem bItem=null;
					TreeItem cItem=null;
					
					System.out.println("making host");
					
					if(aMap.containsKey(a))aItem=aMap.get(a);
					else
					{
						System.out.println("making a");
						aItem=new TreeItem(tree,SWT.NONE);//,new Integer(a).intValue());
						aItem.setText(a+".0.0.0/8");
						//aItem.setItemCount(256);
						aMap.put(a, aItem);
					}
					
					if(bMap.containsKey(b))bItem=bMap.get(b);
					else
					{
						System.out.println("making b");
						bItem=new TreeItem(aItem,SWT.NONE);//,new Integer(b).intValue());
						bItem.setText(a+"."+b+".0.0/16");
						//bItem.setItemCount(256);
						bMap.put(b, bItem);
					}
					
					if(cMap.containsKey(c))cItem=cMap.get(c);
					else
					{
						System.out.println("making c");
						cItem=new TreeItem(bItem,SWT.NONE);//,new Integer(c).intValue());
						cItem.setText(a+"."+b+"."+c+".0/24");
						//cItem.setItemCount(256);
						cMap.put(c, cItem);
					}
					
					hostItem=new TreeItem(cItem,SWT.NONE);//,new Integer(host.split("\\.")[3]).intValue());
					hostItem.setText(host);
					hostMap.put(host, hostItem);
				}
			});		
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	public void addService(Object o)
	{
		try
		{
			final Object[] row=(Object[])o;
			final String host=row[2].toString();
			final String port=row[3].toString();
			final String proto=row[4].toString();
			
			display.syncExec(new Runnable()
			{
				public void run()
				{
					
					if(!hostMap.containsKey(host))
					{
						String a=host.split("\\.")[0];
						String b=host.split("\\.")[1];
						String c=host.split("\\.")[2];
						
						addHost(new Object[]{"","",host,a,b,c});
					}
					
					TreeItem hostItem=hostMap.get(host);
					if(hostItem==null)return;
					
					TreeItem serviceItem=new TreeItem(hostItem,SWT.NONE);
					serviceItem.setText(port+" "+proto);
				}
			});		
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	public void setFocus()
	{
	}

}
